using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
using System.Linq;
using T.FAS.Runtime.Action.SPI;
using T.FAS.Runtime.Action.Service;
using Newtonsoft.Json;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Expression.SPI;
using T.FAS.Runtime.Expression.Entity;
using Newtonsoft.Json.Linq;

namespace T.FAS.Runtime.Expression.Plugin
{
    public class CDOExecutor : DynamicObject, IDynamicActionAdapter
    {
        /// <summary>
        /// JS脚本动态调用Dynamic必备函数
        /// 脚本写法：CDO.Create(CDOcode,ID);
        /// </summary>
        /// <param name = "name">动态调用DynamicObject中的函数名称</param>
        /// <param name = "args">参数信息，参数类型必须增加 params</param>
        /// <returns></returns>
        public object DynamicInvoke(string name, params object[] args)
        {
            try
            {
                return ExcuteAction(name, args);
            }
            catch (Exception e)
            {
                Base.Common.LogUtil.Log(JsonConvert.SerializeObject(e.ToString()), "ExprError");
                throw;
            }
        }

        public dynamic ExcuteAction(string actionID, object[] paramList)
        {
            List<ActionParameter> parameters = new List<ActionParameter>();
            string CDOCode = paramList[0].ToString();
            for (int i = 1; i < paramList.Length; i++)
            {
                parameters.Add(new ActionParameter{Order = i, ParameterValue = paramList[i]});
            }

            ActionType actionType;
            bool isMatchMetadataByCode = true;
            switch (actionID)
            {
                case "NewInstance":
                    if (paramList.Length < 2)
                        throw new FasException(ExprExceptionCode.NotSupported, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Expression_1456423129", "{0}参数个数不正确", actionID)}");
                    actionType = ActionType.CDO_NewInstance;
                    parameters = new List<ActionParameter>();
                    parameters.Add(new ActionParameter{Order = 1, ParameterName = "CDOID", ParameterValue = paramList[0]});
                    parameters.Add(new ActionParameter{Order = 2, ParameterName = "TRecord", ParameterValue = paramList[1]});
                    break;
                case "Create":
                    actionType = ActionType.CDO_Create;
                    break;
                case "Update":
                    actionType = ActionType.CDO_Update;
                    break;
                case "GetDataByID":
                    actionType = ActionType.CDO_GetByID;
                    break;
                case "Delete":
                    actionType = ActionType.CDO_Delete;
                    break;
                case "BatchCreate":
                    if (paramList.Length < 2)
                        throw new FasException(ExprExceptionCode.NotSupported, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Expression_1456423129", "{0}参数个数不正确", actionID)}");
                    actionType = ActionType.CDO_BatchCreate;
                    parameters = new List<ActionParameter>();
                    var batchCreateList = JsonConvert.DeserializeObject<List<JObject>>(JsonConvert.SerializeObject(paramList[1]));
                    parameters.Add(new ActionParameter { Order = 1, ParameterName = "ListTRecord", ParameterValue = batchCreateList });
                    break;
                case "BatchUpdate":
                    actionType = ActionType.CDO_BatchUpdate;
                    parameters = new List<ActionParameter>();
                    var batchUpdateList = JsonConvert.DeserializeObject<List<JObject>>(JsonConvert.SerializeObject(paramList[1]));
                    parameters.Add(new ActionParameter { Order = 1, ParameterName = "ListTRecord", ParameterValue = batchUpdateList });
                    break;
                case "BatchEditUpdate":
                    actionType = ActionType.CDO_BatchEditUpdate;
                    parameters = new List<ActionParameter>();
                    var batchEditUpdateList = JsonConvert.DeserializeObject<List<JObject>>(JsonConvert.SerializeObject(paramList[1]));
                    parameters.Add(new ActionParameter { Order = 1, ParameterName = "ListTRecord", ParameterValue = batchEditUpdateList });
                    break;
                case "BatchDelete":
                    actionType = ActionType.CDO_BatchDelete;
                    parameters = new List<ActionParameter>();
                    var batchDeleteList = JsonConvert.DeserializeObject<List<string>>(JsonConvert.SerializeObject(paramList[1]));
                    parameters.Add(new ActionParameter { Order = 1, ParameterName = "IDS", ParameterValue = batchDeleteList });
                    break;
                case "ChangeState":
                    if (paramList.Length < 4)
                        throw new FasException(ExprExceptionCode.NotSupported, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Expression_1456423129", "{0}参数个数不正确", actionID)}");
                    actionType = ActionType.CDO_ChangeState;
                    parameters = new List<ActionParameter>();
                    parameters.Add(new ActionParameter{Order = 1, ParameterName = "CDOID", ParameterValue = paramList[0]});
                    parameters.Add(new ActionParameter{Order = 2, ParameterName = "ColumnCode", ParameterValue = paramList[1]});
                    parameters.Add(new ActionParameter{Order = 3, ParameterName = "EventKey", ParameterValue = paramList[2]});
                    parameters.Add(new ActionParameter{Order = 4, ParameterName = "record", ParameterValue = paramList[3]});
                    break;
                case "FireEvent":
                    if (paramList.Length < 4)
                        throw new FasException(ExprExceptionCode.NotSupported, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Expression_1456423129", "{0}参数个数不正确", actionID)}");
                    actionType = ActionType.CDO_FireEvent;
                    parameters = new List<ActionParameter>();
                    parameters.Add(new ActionParameter{Order = 1, ParameterName = "CDOID", ParameterValue = paramList[0]});
                    parameters.Add(new ActionParameter{Order = 2, ParameterName = "ColumnCode", ParameterValue = paramList[1]});
                    parameters.Add(new ActionParameter{Order = 3, ParameterName = "EventKey", ParameterValue = paramList[2]});
                    parameters.Add(new ActionParameter{Order = 4, ParameterName = "BillId", ParameterValue = paramList[3]});
                    if (paramList.Length == 5)
                    {
                        parameters.Add(new ActionParameter{Order = 5, ParameterName = "Source", ParameterValue = paramList[4]});
                    }

                    break;
                case "FireEventWithRecord":
                    if (paramList.Length < 4)
                        throw new FasException(ExprExceptionCode.NotSupported, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Expression_1456423129", "{0}参数个数不正确", actionID)}");
                    actionType = ActionType.CDO_FireEventWithRecord;
                    parameters = new List<ActionParameter>();
                    parameters.Add(new ActionParameter{Order = 1, ParameterName = "CDOID", ParameterValue = paramList[0]});
                    parameters.Add(new ActionParameter{Order = 2, ParameterName = "ColumnCode", ParameterValue = paramList[1]});
                    parameters.Add(new ActionParameter{Order = 3, ParameterName = "EventKey", ParameterValue = paramList[2]});
                    parameters.Add(new ActionParameter{Order = 4, ParameterName = "Record", ParameterValue = paramList[3]});
                    if (paramList.Length == 5)
                    {
                        parameters.Add(new ActionParameter{Order = 5, ParameterName = "Source", ParameterValue = paramList[4]});
                    }

                    break;
                default:
                    throw new FasException(ExprExceptionCode.NotSupported, "Unsupported CDO." + actionID);
            }

            TResult result = ActionExecuteService.GetInstance.Execute(CDOCode, actionType, parameters, isMatchMetadataByCode);
            if (result is TCommonResult<JObject>)
            {
                return result as TCommonResult<JObject>;
            }
            else
            {
                return result as TCommonResult<TRecord>;
            }
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            result = DynamicInvoke(binder.Name, args);
            return true;
        }
    }
}